library lib_network;

typedef DataFromJson<T> = T? Function(dynamic data);

typedef APIResultDecoder<T> = APIResult<T> Function(
    Map<String, dynamic> json, DataFromJson<T> dataFromJson);

class APIResult<T> {
  final int code;
  final String? message;
  final T? data;

  static int successCode = 200;

  APIResult(this.code, {this.message, this.data});

  factory APIResult.fromJson(
      Map<String, dynamic> json, DataFromJson<T> dataFromJson,
      {APIResultDecoder<T>? jsonDecoder}) {
    if (jsonDecoder != null) {
      return jsonDecoder(json, dataFromJson);
    } else {
      return APIResult.decoder<T>(json, dataFromJson);
    }
  }

  bool isSuccess() => code == successCode;

  @override
  String toString() =>
      'code: $code, message: $message, data: ${data?.toString()}';

  static APIResult<T> decoder<T>(
      Map<String, dynamic> json, DataFromJson<T> dataFromJson) {
    final int code;
    if (json.containsKey('code') && json['code'] is int) {
      code = json['code'] as int;
    } else {
      throw ArgumentError('Unexpected type for code');
    }

    final String? message;
    if (json.containsKey('msg') && json['msg'] is String) {
      message = json['msg'] as String;
    } else {
      message = null;
    }

    final T? data;
    if (json.containsKey('data') && json['data'] != null) {
      data = dataFromJson(json['data']);
    } else {
      data = null;
    }

    return APIResult(code, message: message, data: data);
  }
}
